package net.kosev.battleships.model.creators;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import net.kosev.battleships.model.Board;
import net.kosev.battleships.model.Field;

/**
 * Ship arrangement generator
 * 
 * @author Nikola
 *
 */
public class AutoBoardCreator implements BoardCreator {
	
	/**
	 * Board of fields, ships will be arranged here
	 */
	private int[][] fields = null;
	
	/**
	 * List of ships that remain to be placed on the board
	 * When ship is placed on the board, it is removed from this list
	 */
	private List<Integer> remainingShips = new ArrayList<Integer>();
	
	/**
	 * Random generator for picking up random ship positions and ship orientation (horizontal, vertical)
	 */
	private Random random = new Random();
	
	/**
	 * Constructor
	 */
	public AutoBoardCreator() {
		// initialize ships with their lengths
		remainingShips.add(4);
		remainingShips.add(3);
		remainingShips.add(3);
		remainingShips.add(2);
		remainingShips.add(2);
		remainingShips.add(2);
		remainingShips.add(1);
		remainingShips.add(1);
		remainingShips.add(1);
		remainingShips.add(1);
	}

	/*
	 * (non-Javadoc)
	 * @see net.kosev.battleships.model.creators.BoardCreator#create()
	 */
	public void create() {
		// create local variables for faster access
		final int size = Board.SIZE;
		final int water = Field.WATER;
		final int ship = Field.SHIP;
		
		while (remainingShips.size() != 0) {
			
			final int orientation = random.nextInt(2); // 0 - horizontal, 1 - vertical
			
			final int shipWidth = (orientation == 0) ? remainingShips.get(0) : 1;
			final int shipHeight = (orientation == 0) ? 1 : remainingShips.get(0);
			
			final int row = random.nextInt(size - shipHeight);
			final int col = random.nextInt(size - shipWidth);
			
			if (fields[row][col] != water) {
				continue;
			}
			
			// bounding box
			final int colMin = col - 1;
			final int colMax = col + shipWidth;
			final int rowMin = row - 1;
			final int rowMax = row + shipHeight;
			
			if (!checkForCollision(rowMin, rowMax, colMin, colMax)) {
				if (orientation == 0) {
					for (int i = 0; i < shipWidth; i++) {
						fields[row][col + i] = ship;
					}
				} else {
					for (int i = 0; i < shipHeight; i++) {
						fields[row + i][col] = ship;
					}
				}
				remainingShips.remove(0);
			}
		}
	}
	
	/**
	 * Check if generated ship is in collision with board or other ships
	 * 
	 * @param rowMin	Minimum row of ship's bounding box
	 * @param rowMax	Maximum row of ship's bounding box
	 * @param colMin	Minimum column of ship's bounding box
	 * @param colMax	Maximum column of ship's bounding box
	 * 
	 * @return	Returns true if there is collision and false if ship is ready to go
	 */
	private boolean checkForCollision(int rowMin, int rowMax, int colMin, int colMax) {
		// create local variables for faster access
		final int size = Board.SIZE;
		final int water = Field.WATER;
		
		// check board
		if (colMin < -1 || rowMin < -1 || colMax > size || rowMax > size) {
			return true;
		}
		
		// check each field
		for (int i = 0; i < size; i++) {
			for (int j = 0; j < size; j++) {
				if (fields[i][j] == water) {
					continue;
				} else {
					if (i >= rowMin && i <= rowMax && j >= colMin && j <= colMax) {
						return true;
					}
				}
			}
		}
		
		return false;
	}

	/*
	 * (non-Javadoc)
	 * @see net.kosev.battleships.model.creators.BoardCreator#setFields(int[][])
	 */
	public void setFields(int[][] fields) {
		this.fields = fields;
	}
	
}
